﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Technullogy.Web.UI
{
    [ToolboxData("<{0}:VideoJS runat=server></{0}:VideoJS>")]
    public class VideoJS : WebControl
    {
        #region Properties
        [Description("The poster image is placeholder for the video before it plays. It's also used as the image fallback for devices that don't support HTML5 Video or Flash. The poster doesn't work in all browsers, so VideoJS creates a new image with the poster source and places it over the video")]
        public String PosterImage { get; set; }

        [Description("Supported by Webkit browsers (Safari, Chrome, iPhone/iPad) and Internet Explorer 9. Also supported by Flash 9 and higher, so can double as the Flash source.")]
        public Uri Mp4Source { get; set; }

        [Description("Supported by newer versions of Firefox, Chrome, and Opera.")]
        public Uri WebMSource { get; set; }

        private bool _enableFlashFailover = true;
        [Description("Used for browsers and devices that don't support HTML5 video but do support Flash. You can replace the Flash fallback with the flash video player of your choice. Flash 9 and above will play the MP4 source."), 
         DefaultValue(true)]
        public bool EnableFlashFailover 
        {
            get
            {
                return _enableFlashFailover;
            }
            set
            {
                _enableFlashFailover = value;
            }
        }

        [Description("Used for browsers and devices that don't support HTML5 video but do support Flash. You can replace the Flash fallback with the flash video player of your choice. Flash 9 and above will play the MP4 source."),
         DefaultValue(true)]
        public Uri FlashSource { get; set; }

        private bool _useMp4 = true;
        [Description("If set to True and the client is using FlashSource, Flash 9 and above will use the Mp4Source."),
         DefaultValue(true)]
        public bool UseMp4 
        {
            get
            {
                return _useMp4;
            }
            set
            {
                _useMp4 = value;
            }
        }

        [Description("Supported by Firefox, Opera, Chrome, and newer versions of Safari. Unfortunately it's not as good as WebM and MP4.")]
        public Uri OggSource { get; set; }

        private bool _displayDownloadLinks = false;
        [Description("If you want to support devices that don't support HTML5 or Flash, include links to the video source. These devices are typically lower-tech mobile phones, and sometimes they can still play the video by downloading it."),
         DefaultValue(false)]
        public bool DisplayDownloadLinks 
        {
            get
            {
                return _displayDownloadLinks;
            }
            set
            {
                _displayDownloadLinks = value;
            }
        }

        private bool _displayVideoJSLink = true;
        [Description("Links back help promote the VideoJS project and increase the community, which speeds development."),
         DefaultValue(true)]
        public bool DisplayVideoJSLink 
        {
            get
            {
                return _displayVideoJSLink;
            }
            set
            {
                _displayVideoJSLink = value;
            }
        }

        [Description("Select this if you want the video to start downloading as soon the user loads the page. Typically good if you want playback to be immediate, but can use unnecessary bandwidth.")]
        public bool EnableVideoPreload { get; set; }

        private bool _enableAutoPlay = false;
        [Description("Select this if you want the video to start playing as soon as the page is loaded. Can be annoying, so only use if the page is dedicated to the video that's being played."), 
         DefaultValue(false)]
        public bool EnableAutoPlay 
        {
            get
            {
                return _enableAutoPlay;
            }
            set
            {
                _enableAutoPlay = value;
            }
        }

        private Unit _width = Unit.Pixel(640);
        public override Unit Width
        {
            get
            {
                return _width;
            }
            set
            {
                base.Width = value;
                _width = value;
            }
        }

        private Unit _height = Unit.Pixel(264);
        public override Unit Height
        {
            get
            {
                return _height;
            }
            set
            {
                base.Height = value;
                _height = value;
            }
        }

        private EmbeddedSkin _skin = EmbeddedSkin.VideoJS;
        [DefaultValue(EmbeddedSkin.VideoJS)]
        public EmbeddedSkin Skin 
        {
            get
            {
                return _skin;
            }
            set
            {
                _skin = value;
            }
        }

        public enum EmbeddedSkin
        {
            Hulu,
            VideoJS,
            Vimeo,
            YouTube
        }
        #endregion

        #region Methods

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            // Register Scripts
            Page.ClientScript.RegisterClientScriptResource(GetType(), "Technullogy.Web.UI.VideoJS.Scripts.video.js");
            Page.ClientScript.RegisterClientScriptResource(GetType(), "Technullogy.Web.UI.VideoJS.Scripts.clientScripts.js");

            // Register CSS
            RegisterCss(EmbeddedSkin.VideoJS);
            if (Skin != EmbeddedSkin.VideoJS)
                RegisterCss(Skin);
        }

        protected override void RenderContents(HtmlTextWriter output)
        {
            if (Mp4Source == null && WebMSource == null && OggSource == null)
                throw new Exception("Mp4Source, WebMSource and OggSource are all NULL! At least 1 must be set!");

            String cssClass;
            switch (Skin)
            {
                default:
                case EmbeddedSkin.VideoJS:
                    cssClass = String.Empty;
                    break;

                case EmbeddedSkin.Hulu:
                    cssClass = " hu-css";
                    break;
                
                case EmbeddedSkin.Vimeo:
                    cssClass = " vim-css";
                    break;

                case EmbeddedSkin.YouTube:
                    cssClass = " tube-css";
                    break;
            }

            StringBuilder contents = new StringBuilder();
            contents.AppendFormat(@"<div class=""video-js-box{0}"">", cssClass);

            String preload = EnableVideoPreload ? @"preload=""auto""" : @"preload=""none""";
            String autoplay = EnableAutoPlay ? "autoplay" : String.Empty;
            String poster = String.IsNullOrEmpty(PosterImage) ? String.Empty : String.Format(@"poster=""{0}""", PosterImage);

            contents.AppendFormat(@"<video id=""example_video_1"" class=""video-js"" width=""{0}"" height=""{1}"" controls=""controls"" {2} {3} {4}>", Width, Height, preload, poster, autoplay);

            if (Mp4Source != null)
                contents.AppendFormat(@"<source src=""{0}"" type='video/mp4; codecs=""avc1.42E01E, mp4a.40.2""' />", Mp4Source);

            if (WebMSource != null)
                contents.AppendFormat(@"<source src=""{0}"" type='video/webm; codecs=""vp8, vorbis""' />", WebMSource);

            if (OggSource != null)
                contents.AppendFormat(@"<source src=""{0}"" type='video/ogg; codecs=""theora, vorbis""' />", OggSource);

            // <!-- Flash Fallback. Use any flash video player here. Make sure to keep the vjs-flash-fallback class. -->
            contents.AppendFormat(@"<object id=""flash_fallback_1"" class=""vjs-flash-fallback"" width=""{0}"" height=""{1}"" type=""application/x-shockwave-flash"" data=""http://releases.flowplayer.org/swf/flowplayer-3.2.1.swf"">", Width, Height);
            contents.Append(@"<param name=""movie"" value=""http://releases.flowplayer.org/swf/flowplayer-3.2.1.swf"" />");
            contents.Append(@"<param name=""allowfullscreen"" value=""true"" />");

            if (EnableFlashFailover)
            {
                if (!UseMp4 && FlashSource == null)
                    throw new Exception("FlashSource property must be set when EnableFlashFailover is true and Mp4 is false!");

                if (UseMp4 && Mp4Source == null)
                    throw new Exception("Mp4Source is NULL!");

                Uri flashPlaylistSource = UseMp4 ? Mp4Source : FlashSource;
                contents.Append(@"<param name=""flashvars"" value='config={");
                contents.AppendFormat(@"""playlist"":[""{0}"", ", PosterImage);
                contents.Append(@"{");
                contents.AppendFormat(@"""url"": ""{0}"",""autoPlay"":{1},""autoBuffering"":true", flashPlaylistSource, EnableAutoPlay.ToString().ToLower());
                contents.Append(@"}]}' />");

                /// <!-- Image Fallback. Typically the same as the poster image. -->
                contents.AppendFormat(@"<img src=""{0}"" width=""{1}"" height=""{2}"" alt=""Poster Image"" title=""No video playback capabilities."" />", PosterImage, Width, Height);
                contents.Append(@"</object>");
            }

            contents.Append(@"</video>");

            if (DisplayDownloadLinks)
            {
                // <!-- Download links provided for devices that can't play video in the browser. -->
                contents.Append(@"<p class=""vjs-no-video""><strong>Download Video:</strong>");

                if (Mp4Source != null)
                    contents.AppendFormat(@" <a href=""{0}"">MP4</a> ", Mp4Source);

                if (WebMSource != null)
                    contents.AppendFormat(@" <a href=""{0}"">WebM</a> ", WebMSource);

                if (OggSource != null)
                    contents.AppendFormat(@" <a href=""{0}"">Ogg</a></p>", OggSource);
            }

            // <!-- Support VideoJS by keeping this link. -->
            if (DisplayVideoJSLink)
                contents.Append(@"<br /><a href=""http://videojs.com"">HTML5 Video Player</a> by VideoJS");

            contents.Append(@"</div>");
            output.Write(contents.ToString());
        }

        private void RegisterCss(EmbeddedSkin skin)
        {
            String webResource = String.Format(@"Technullogy.Web.UI.VideoJS.Skins.{0}.css", skin);
            String webResourceUrl = Page.ClientScript.GetWebResourceUrl(typeof(VideoJS), webResource);
            String cssLink = String.Format(@"<link rel=""stylesheet"" text=""text/css"" href=""{0}"" />", webResourceUrl);
            if (!Page.ClientScript.IsClientScriptBlockRegistered(GetType(), webResource))
                Page.ClientScript.RegisterClientScriptBlock(GetType(), webResource, cssLink);
        }
        #endregion
    }
}
